#pragma once
#include <iostream>
#include <memory>
#include <mutex>

    template <typename T>
    class Singleton {
     protected:
      Singleton() = default;
      Singleton(const Singleton<T>&) = delete;
      Singleton& operator=(Singleton<T>&) = delete;
      Singleton( Singleton<T>&&) = delete;
      Singleton& operator=(Singleton<T>&&) = delete;

      static std::shared_ptr<T> _Instance;
      static std::once_flag _Flag;

     public:
      static std::shared_ptr<T> GetInstance() {
        std::call_once(_Flag, [&]() { _Instance = std::shared_ptr<T>(new T);
                                  
        
        });
        return _Instance;
      }
      void PrintAddress() { std::cout << _Instance.get() << std::endl; }

      ~Singleton() { std::cout << "this is singleton destruct" << std::endl; }
    };

    template <typename T>
    std::shared_ptr<T> Singleton<T>::_Instance = nullptr;

    template <typename T>
    std::once_flag Singleton<T>::_Flag;